package org.pewpew.server;

import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.pewpew.model.WorldState;

@SuppressWarnings("serial")
public class GameStateServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger(GameStateServlet.class.getName());

	private static final String PARAM_ORIENTATION = "or";
	private static final String PARAM_ACTION = "action";
	private static final String PARAM_LATITUDE = "la";
	private static final String PARAM_LONGITUDE = "lo";
	private static final String PARAM_USER = "user";
	private static final String PARAM_VALUE_SHOOT = "shoot";

	public static WorldState INSTANCE = null;

	public GameStateServlet() {
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		try {
			WorldState game = GameStateServlet.getWorldState();

			String username = request.getParameter(PARAM_USER);
			if (username != null) {
				double latitude = parseDouble(request, PARAM_LATITUDE);
				double longitude = parseDouble(request, PARAM_LONGITUDE);
				double orientation = parseDouble(request, PARAM_ORIENTATION);
				
				game.updatePlayerLocation(username, latitude, longitude, orientation);

				String action = request.getParameter(PARAM_ACTION);
				if (action != null && action.equals(PARAM_VALUE_SHOOT)) {
					game.shoot(username);
				}
			}
			
			String jsonGameState = game.toJSON();
			response.getWriter().println(jsonGameState);
			if (username != null) {
				saveWorldState(jsonGameState);
			}

			log.log(Level.INFO, jsonGameState);
		} catch (NumberFormatException e) {
			log.log(Level.WARNING, "Cannot parse double :" + e.getMessage(), e);
		} catch (InvalidParameterException e) {
			log.log(Level.WARNING, e.getMessage());
		} catch (Exception e) {
			log.log(Level.WARNING, e.getMessage(), e);
		}
	}

	private double parseDouble(HttpServletRequest request, String name) throws Exception {
		String parameter = request.getParameter(name);
		if (name == null) {
			throw new InvalidParameterException(name + " is not provided, corresponding parameter should be specified");
		}

		if (parameter == null) {
			throw new InvalidParameterException("Parameter " + name + " was not supplied in the request.");
		}

		// NumberFormatException will be caught in servlet
		try {
			return Double.valueOf(parameter);
		} catch (Exception e) {
			throw new InvalidParameterException("Parameter " + name + "=[" + parameter + "] and is invalid");
		}
	}

	public static WorldState getWorldState() {
		return Persistence.getWorldState();
	}

	private void saveWorldState(String worldStateString) {
		Persistence.saveWorldState(worldStateString);
	}

}
